#include "shell_obd.h"
#include "includes.h"
#include "globals.h"


shell_cmds obd_shell_cmds = {
     3,
     {
          {
               "help",
               " Print available shell commands",
               shell_cmd_help,
          },
          /*
          {
               "eon",
               "  Turn echo on",
               shell_cmd_eon,
          },
          {
               "eoff",
               " Turn echo off",
               shell_cmd_eoff,
          },
          */
          {
              "filter",
              " filter can id  ",
              shell_filter_can,
          },
          {
              "send",
              " Send can data ",
              shell_send_can,
          },
     },
};

int do_echo = 1;

int shell_cmd_help(shell_cmd_args *args)
{
     int i;

     shell_ok();

     shell_println("Vehicle can tool:");

     for(i = 0; i < obd_shell_cmds.count; i++) {
          shell_print("- ");
          shell_print((char *)obd_shell_cmds.cmds[i].cmd);
          shell_print("  ");
          shell_println((char *)obd_shell_cmds.cmds[i].desc);

          // XBee seams not to be fast enough when it gets send a lot of data at once ...
          //delay(1000);
     }

     shell_eod();

     return 0;
}

int shell_cmd_eon(shell_cmd_args *args)
{
     shell_ok();

     shell_println("echo on");

     do_echo = 1;

     shell_eod();

     return 0;
}

int shell_cmd_eoff(shell_cmd_args *args)
{
     shell_ok();

     shell_println("echo off");

     do_echo = 0;

     shell_eod();

     return 0;
}

void usage_filter_can(void)
{
    shell_println("\tusage: filter [canid1] [canid2] ...");
}

int shell_filter_can(shell_cmd_args *args)
{
    static uint16_t filter_id = 0xffff;
    static uint16_t mask_id = 0xffff;
    uint16_t temp_id = 0x0000;

    int len = 0;
    int i = 0;

    if(args->count == 0) {
        shell_println("ERR: invalid parameters");
        usage_filter_can();
        shell_eod();
        return 1;
    }

    len = args->count;
    temp_id = shell_parse_hex(args->args[0].val);
    filter_id = temp_id;
    mask_id = temp_id;

    for(i = 1; i < len; i++) {
        temp_id = shell_parse_hex(args->args[i].val);
        filter_id &= temp_id;
        mask_id = ~(mask_id ^ temp_id);
    }

    printk("filter id = %4x, mask id = %4x\r\n",
            filter_id, mask_id);
	flexcan_filter(filter_id, filter_id, mask_id, mask_id);
    shell_ok();

    return 0;
}

void usage_send_can(void)
{
    shell_println("\tusage: send [canid] xx xx xx xx ...");
}

int shell_send_can(shell_cmd_args *args)
{
    int len = 0;
    int i = 0;
    uint16_t id;
    int b;

    CanTxMsg msg = 
    {
	    0x7e0, 0x18db33f1,
	    CAN_ID_STD, CAN_RTR_DATA,
	    8,
	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    if(args->count < 2) {
        shell_println("ERR: invalid parameters");
        usage_send_can();
        shell_eod();
        return 1;
    }

    id = shell_parse_hex(args->args[0].val);

    msg.StdId = id;
    len = args->count - 1;

    msg.DLC = len;
    for(i = 0; i < len; i++) {
        b = shell_parse_hex(args->args[1 + i].val);
        msg.Data[i] = (uint8_t)b;
    //    printf("[%d] = %02x\r\n", i, (uint8_t)b);
    }

    flexcan_send_frame2(&msg);
    shell_ok();

    return 0;
}

void shell_prompt(void)
{
    shell_print("$> ");
}

int shell_process(char *cmd_line)
{
    return shell_process_cmds(&obd_shell_cmds, cmd_line);
}

void USART2_IRQHandler(void)
{
    uint8_t data;
    static char cmd_line[SHELL_MAX_CMD_LINE];
    static int i = 0;

    if(USART_GetITStatus(USART2, USART_IT_RXNE)
            != RESET) {
        data = USART_ReceiveData(USART2);

        if(do_echo) {
            printf("%c", data);
        }

        if(data == '\r') {
            shell_println("");
            if(i > 0) {
                cmd_line[i] = 0;

                if(shell_process(cmd_line) 
                        != SHELL_PROCESS_OK) {
                    //shell_error();
                    //shell_eod();
                }
            }

            i = 0;

            shell_prompt();
        } else if(data != '\n') {
            cmd_line[i ++] = data;
        }

        if(i > SHELL_MAX_CMD_LINE - 1)
            i = 0;
    }

    if(USART_GetITStatus(USART2, USART_IT_TXE)
            != RESET) {
        USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
    }
}
